package com.cjkj.equipment.utils;

import com.cjkj.common.core.constant.SleepConstants;
import com.cjkj.common.core.exception.ServiceException;
import com.cjkj.equipment.domain.MonitorPadData;
import com.cjkj.equipment.domain.dto.BreathAndHeartAVGDto;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 睡眠报告公共工具类
 * @author cjkj
 * @date 2024-08-30
 */
public class SleepStageUtil {

    /**
     * 计算睡眠分期状态
     * @param benchmarkDataHeartRateAvg 基准数据平均心率
     * @param heartRate 当前参与计算的心率
     * @param benchmarkDataBreathRateAvg 基准数据平均呼吸率
     * @param breathRate 当前参与计算的呼吸率
     * @param bodyMove 体动情况
     * @return 睡眠分期
     */
    public static String calculateSleepStage(int benchmarkDataHeartRateAvg, int heartRate, int benchmarkDataBreathRateAvg, int breathRate, String bodyMove){
        /*
         * 睡眠分期判断标准
         * 将觉醒期的平均心率和呼吸率和觉醒期心率和呼吸下降20%的划为睡眠期间hRange/bRange；
         * 将睡眠期间平均分成三个区间：
         * 心率分期：
         * 深睡期：hAvg - hRang < heart <= hAvg -hRang * (2/3)；只要小于hAvg -hRang * (2/3) 即为深睡
         * 浅睡期：hAvg -hRang * 2/3< heart <= hAvg -hRang * (1/3)
         * 快速眼动期：hAvg -hRang * (1/3) < heart <= hAvg   本次不计算快速眼动期
         * 清醒：heart > hAvg -hRang * (1/3)
         *
         * 呼吸率分期：
         * 深睡期：bAvg - bRang < breath <= bAvg -bRang * (2/3)；只要小于bAvg -bRang * (2/3) 即为深睡
         * 浅睡期：bAvg -bRang * 2/3< breath <= bAvg -bRang * (1/3)
         * 快速眼动期：bAvg -bRang * (1/3) < breath <= bAvg   本次不计算快速眼动期
         * 清醒：breath > bAvg -bRang * (1/3)
         */

        double h = benchmarkDataHeartRateAvg - 2 * (benchmarkDataHeartRateAvg * 0.2 / 3);
        double h1 = benchmarkDataHeartRateAvg - (benchmarkDataHeartRateAvg * 0.2 / 3);

        // 区间数据按心率判断的睡眠分期状态
        int hSleepStage = 0;
        // 根据心率判断睡眠分期
        int wideAwake = Integer.parseInt(SleepConstants.SLEEP_STAGE_WIDE_AWAKE);
        if(h >= heartRate && SleepConstants.SLEEP_BODYMOVE_FALSE.equals(bodyMove)){
            // 深睡
            hSleepStage = Integer.parseInt(SleepConstants.SLEEP_STAGE_DEEP_SLEEP);
        }else if((h >= heartRate && SleepConstants.SLEEP_BODYMOVE_TRUE.equals(bodyMove))
                || (h < heartRate && h1 >= heartRate)){
            // 浅睡
            hSleepStage = Integer.parseInt(SleepConstants.SLEEP_STAGE_LIGHT_SLEEP);
        } else {
            // 清醒
            hSleepStage = wideAwake;
        }

        double b = benchmarkDataBreathRateAvg - 2 * (benchmarkDataBreathRateAvg * 0.2 / 3);
        double b1 = benchmarkDataBreathRateAvg - (benchmarkDataBreathRateAvg * 0.2 / 3);
        // 区间数据按呼吸率判断的睡眠分期状态
        int bSleepStage = 0;
        // 根据呼吸率判断睡眠分期
        if(breathRate <= b && SleepConstants.SLEEP_BODYMOVE_FALSE.equals(bodyMove)){
            // 深睡
            bSleepStage = Integer.parseInt(SleepConstants.SLEEP_STAGE_DEEP_SLEEP);
        }else if((breathRate <= b && SleepConstants.SLEEP_BODYMOVE_TRUE.equals(bodyMove))
                || (breathRate > b && breathRate <= b1)){
            // 浅睡
            bSleepStage = Integer.parseInt(SleepConstants.SLEEP_STAGE_LIGHT_SLEEP);
        } else {
            // 清醒
            bSleepStage = wideAwake;
        }

        // 最终判断区间数据的睡眠分期状态
        String sleepStage = "";
        if(hSleepStage != bSleepStage){
            if(hSleepStage == wideAwake || bSleepStage == wideAwake) {
                // 如果心率分期和呼吸分期有一个判断为清醒，则最终睡眠分期状态设为不是清醒的那个数据
                sleepStage = String.valueOf(hSleepStage != wideAwake ? hSleepStage : bSleepStage);
            } else {
                sleepStage = String.valueOf(SleepConstants.SLEEP_BODYMOVE_FALSE.equals(bodyMove) ? Math.max(hSleepStage, bSleepStage) : Math.min(hSleepStage, bSleepStage));
            }
        } else {
            sleepStage =  String.valueOf(bSleepStage);
        }

        return sleepStage;
    }

    /**
     * @Description: 计算心率和呼吸率的平均值
     * @Creator: 93000
     * @Date: 2022/11/8 15:46
     * @Param: dataList 基准数据
     * @return:
     */
    public static BreathAndHeartAVGDto calculateAVG(List<MonitorPadData> dataList){
        BreathAndHeartAVGDto avgDto = new BreathAndHeartAVGDto();
        if(dataList == null || dataList.isEmpty()){
            throw new ServiceException("计算呼吸率、心率平均值，参数不能为空！");
        }
        // 算出基准数据的平均呼吸率
        int breathRateAvg = dataList.stream().collect(Collectors.averagingInt(MonitorPadData::getBreathRate)).intValue();
        breathRateAvg = Math.max(breathRateAvg, 16);
        // 算出基准数据的平均心率
        int heartRateAvg = dataList.stream().collect(Collectors.averagingInt(MonitorPadData::getHeartRate)).intValue();
        heartRateAvg = Math.max(heartRateAvg, 60);

        avgDto.setHeartRateAvg(heartRateAvg);
        avgDto.setBreathRateAvg(breathRateAvg);
        return avgDto;
    }

    /**
     * 报告日期
     * @param acquisitionTime 数据采集时间
     * @return
     */
    public static Date getReportDay(Date acquisitionTime){
        /*
         * 1.判断采集的时间是否在当天的下午六点过后，或者第二天的早上八点之前；如果在时间范围内；
         *  a.采集时间在当前时间下午六点以后，则报告时间为当天yyyy-mm-dd;
         *  b.采集时间在当天早上八点之前，则报告时间为前一天；
         */
        Date reportDay = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(acquisitionTime);
        //下午18点
        calendar.set(Calendar.HOUR_OF_DAY, 18);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date time18 = calendar.getTime();
        //早上8点
        calendar.set(Calendar.HOUR_OF_DAY, 8);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date time08 = calendar.getTime();

        if(acquisitionTime.getTime() >= time18.getTime()){
            // 18点后
            reportDay = calendar.getTime();
        }else if(acquisitionTime.getTime() <= time08.getTime()){
            // 8点前
            calendar.add(Calendar.DAY_OF_MONTH,-1);
            reportDay = calendar.getTime();
        }

        return reportDay;
    }
}
